package com.bky.redis;

import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;

import java.util.List;
import java.util.Map;
import java.util.Set;

@Service
public class RedisService {

	//有的工程需要，有的工程不需要。设置required=false，有就注入，没有就不注入。
    @Autowired(required = false)
    private ShardedJedisPool shardedJedisPool;

    private <T> T execute(Function<ShardedJedis, T> function) {
        ShardedJedis shardedJedis = null;
        try {
            // 从连接池中获取到jedis分片对象
            shardedJedis = shardedJedisPool.getResource();
            return function.execute(shardedJedis);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != shardedJedis) {
                // 关闭，检测连接是否有效，有效则放回到连接池中，无效则重置状态
                shardedJedis.close();
            }
        }
        return null;
    }

    /**
     * 保存数据到redis中
     * 
     * @param key
     * @param value
     * @return
     */
    public String set(final String key, final String value) {
        return this.execute(new Function<ShardedJedis, String>() {
            @Override
            public String execute(ShardedJedis shardedJedis) {
                return shardedJedis.set(key, value);
            }

        });
    }

    /**
     * 保存数据到redis中，生存时间单位是：秒
     * 
     * @param key
     * @param value
     * @param seconds
     * @return
     */
    public String set(final String key, final String value, final Integer seconds) {
        return this.execute(new Function<ShardedJedis, String>() {
            @Override
            public String execute(ShardedJedis shardedJedis) {
                String result = shardedJedis.set(key, value);
                shardedJedis.expire(key, seconds);//设置生存时间
                return result;
            }

        });
    }

    /**
     * 从redis中获取数据
     * 
     * @param key
     * @return
     */
    public String get(final String key) {
        return this.execute(new Function<ShardedJedis, String>() {
            @Override
            public String execute(ShardedJedis shardedJedis) {
                return shardedJedis.get(key);
            }

        });
    }

    /**
     * 设置key生存时间，单位：秒
     * 
     * @param key
     * @param seconds
     * @return
     */
    public Long expire(final String key, final Integer seconds) {
        return this.execute(new Function<ShardedJedis, Long>() {
            @Override
            public Long execute(ShardedJedis shardedJedis) {
                return shardedJedis.expire(key, seconds);
            }

        });
    }

    /**
     * 从redis中删除数据
     * 
     * @param key
     * @return
     */
    public Long del(final String key) {
        return this.execute(new Function<ShardedJedis, Long>() {
            @Override
            public Long execute(ShardedJedis shardedJedis) {
                return shardedJedis.del(key);
            }
        });
    }

    /**
     * 判断key是否存在
     * @param key
     * @return
     */
    public Boolean exists(final String key){
        return this.execute(new Function<ShardedJedis, Boolean>() {
            @Override
            public Boolean execute(ShardedJedis shardedJedis) {
                return shardedJedis.exists(key);
            }
        });
    }
    /**
     * 保存Object到redis中
     *
     * @param key
     * @param value
     * @return
     */
    public <T> String setObject(final String key, final T value) {
        return this.execute(new Function<ShardedJedis, String>() {
            @Override
            public String execute(ShardedJedis shardedJedis) {
                return shardedJedis.set(key, JSONObject.toJSONString(value, true));
            }

        });
    }

    /**
     * 字符串数据类型setex
     * @param key
     * @param seconds
     * @param value
     * @return
     */
    public String setex(final String key, final int seconds, final String value) {
        return this.execute(new Function<ShardedJedis, String>() {
            @Override
            public String execute(ShardedJedis shardedJedis) {
                return shardedJedis.setex(key, seconds, value);
            }
        });
    }

    /**
     * 移除给定 key 的过期时间，使得 key 永不过期
     * @param key
     * @return
     */
    public Long persist(final String key) {
        return this.execute(new Function<ShardedJedis, Long>() {
            @Override
            public Long execute(ShardedJedis shardedJedis) {
                return shardedJedis.persist(key);
            }
        });
    }
    /**
     * 保存Object到redis中,并设置过期时间
     * @param key
     * @param value
     * @param expire
     * @param <T>
     * @return
     */
    public <T> String setObject(final String key, final T value, final Integer expire) {
        return this.execute(new Function<ShardedJedis, String>() {
            @Override
            public String execute(ShardedJedis shardedJedis) {
                return shardedJedis.setex(key, expire, JSONObject.toJSONString(value, true));
            }

        });
    }

    /**
     * hash数据类型set
     * @param key
     * @param field
     * @param value
     * @return
     */
    public Long hset(final String key, final String field, final String value){
        return this.execute(new Function<ShardedJedis, Long>() {
            @Override
            public Long execute(ShardedJedis shardedJedis) {
                return shardedJedis.hset(key, field, value);
            }
        });
    }

    /**
     * hash数据类型get
     * @param key
     * @param field
     * @return
     */
    public String hget(final String key, final String field){
        return this.execute(new Function<ShardedJedis, String>() {
            @Override
            public String execute(ShardedJedis shardedJedis) {
                return shardedJedis.hget(key, field);
            }
        });
    }

    /**
     * 列表数据类型lpush
     * @param key
     * @param values
     * @return
     */
    public Long lpush(final String key, final String...values){
        return this.execute(new Function<ShardedJedis, Long>() {
            @Override
            public Long execute(ShardedJedis shardedJedis) {
                return shardedJedis.lpush(key, values);
            }
        });
    }

    /**
     * 列表数据类型lindex
     * @param key
     * @param index
     * @return
     */
    public String lindex(final String key, final Long index){
        return this.execute(new Function<ShardedJedis, String>() {
            @Override
            public String execute(ShardedJedis shardedJedis) {
                return shardedJedis.lindex(key, index);
            }
        });
    }

    /**
     * 集合数据类型sadd
     * @param key
     * @param members
     * @return
     */
    public Long sadd(final String key, final String... members) {
        return this.execute(new Function<ShardedJedis, Long>() {
            @Override
            public Long execute(ShardedJedis shardedJedis) {
                return shardedJedis.sadd(key, members);
            }
        });
    }

    /**
     * 集合数据类型smembers
     * @param key
     * @return
     */
    public Set<String> smembers(final String key) {
        return this.execute(new Function<ShardedJedis, Set<String>>() {
            @Override
            public Set<String> execute(ShardedJedis shardedJedis) {
                return shardedJedis.smembers(key);
            }
        });
    }

    /**
     * 有序集合数据类型zadd
     * @param key
     * @param score
     * @param member
     * @return
     */
    public Long zadd(final String key, final double score, final String member) {
        return this.execute(new Function<ShardedJedis, Long>() {
            @Override
            public Long execute(ShardedJedis shardedJedis) {
                return shardedJedis.zadd(key, score, member);
            }
        });
    }

    /**
     * 有序集合数据类型zmadd
     * @param key
     * @param scoreMembers
     * @return
     */
    public Long zmadd(final String key, final Map<String, Double> scoreMembers) {
        return this.execute(new Function<ShardedJedis, Long>() {
            @Override
            public Long execute(ShardedJedis shardedJedis) {
                return shardedJedis.zadd(key, scoreMembers);
            }
        });
    }

    /**
     * 有序集合数据类型zrange 升序
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Set<String> zrange(final String key, final long start, final long end) {
        return this.execute(new Function<ShardedJedis, Set<String>>() {
            @Override
            public Set<String> execute(ShardedJedis shardedJedis) {
                return shardedJedis.zrange(key, start, end);
            }
        });
    }

    /**
     * 有序集合数据类型zrevrange 降序
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Set<String> zrevrange(final String key, final long start, final long end) {
        return this.execute(new Function<ShardedJedis, Set<String>>() {
            @Override
            public Set<String> execute(ShardedJedis shardedJedis) {
                return shardedJedis.zrevrange(key, start, end);
            }
        });
    }

    /**
     * 有序集合数据类型zrank 倒序名次 从零开始
     * @param key
     * @param member
     * @return
     */
    public Long zrank(final String key, final String member) {
        return this.execute(new Function<ShardedJedis, Long>() {
            @Override
            public Long execute(ShardedJedis shardedJedis) {
                return shardedJedis.zrank(key, member);
            }
        });
    }

    /**
     * 有序集合数据类型zrevrank 正序名次 从零开始
     * @param key
     * @param member
     * @return
     */
    public Long zrevrank(final String key, final String member) {
        return this.execute(new Function<ShardedJedis, Long>() {
            @Override
            public Long execute(ShardedJedis shardedJedis) {
                return shardedJedis.zrevrank(key, member);
            }
        });
    }

    /**
     * 打印字符串
     * @param string
     * @return
     */
    public String echo(final String string) {
        return this.execute(new Function<ShardedJedis, String>() {
            @Override
            public String execute(ShardedJedis shardedJedis) {
                return shardedJedis.echo(string);
            }
        });
    }

    /**
     * 返回key的数据类型
     * @param key
     * @return
     */
    public String type(final String key) {
        return this.execute(new Function<ShardedJedis, String>() {
            @Override
            public String execute(ShardedJedis shardedJedis) {
                return shardedJedis.type(key);
            }
        });
    }

    /**
     * 查询key剩余时间 -1 代表永久不过期
     * @param key
     * @return
     */
    public Long ttl(final String key) {
        return this.execute(new Function<ShardedJedis, Long>() {
            @Override
            public Long execute(ShardedJedis shardedJedis) {
                return shardedJedis.ttl(key);
            }
        });
    }

    /**
     * key赋值value第一次返回1 其他都返回0
     * @param key
     * @param value
     * @return
     */
    public Long setnx(final String key, final String value) {
        return this.execute(new Function<ShardedJedis, Long>() {
            @Override
            public Long execute(ShardedJedis shardedJedis) {
                return shardedJedis.setnx(key, value);
            }
        });
    }

    /**
     * 自增
     * @param key
     * @return
     */
    public Long incr(final String key) {
        return this.execute(new Function<ShardedJedis, Long>() {
            @Override
            public Long execute(ShardedJedis shardedJedis) {
                return shardedJedis.incr(key);
            }
        });
    }

    /**
     * 自增相应步长
     * @param key
     * @param step
     * @return
     */
    public Long incrBy(final String key, final long step) {
        return this.execute(new Function<ShardedJedis, Long>() {
            @Override
            public Long execute(ShardedJedis shardedJedis) {
                return shardedJedis.incrBy(key, step);
            }
        });
    }

    /**
     * 自减
     * @param key
     * @return
     */
    public Long decr(final String key) {
        return this.execute(new Function<ShardedJedis, Long>() {
            @Override
            public Long execute(ShardedJedis shardedJedis) {
                return shardedJedis.decr(key);
            }
        });
    }

    /**
     * 自减相应步长
     * @param key
     * @param step
     * @return
     */
    public Long decrBy(final String key, final long step) {
        return this.execute(new Function<ShardedJedis, Long>() {
            @Override
            public Long execute(ShardedJedis shardedJedis) {
                return shardedJedis.decrBy(key, step);
            }
        });
    }

    /**
     * key值末尾追加值
     * @param key
     * @param value
     * @return
     */
    public Long append(final String key, final String value) {
        return this.execute(new Function<ShardedJedis, Long>() {
            @Override
            public Long execute(ShardedJedis shardedJedis) {
                return shardedJedis.append(key, value);
            }
        });
    }

    /**
     * 获取key的value的子串
     * @param key
     * @param start
     * @param end
     * @return
     */
    public String substr(final String key, final int start, final int end) {
        return this.execute(new Function<ShardedJedis, String>() {
            @Override
            public String execute(ShardedJedis shardedJedis) {
                return shardedJedis.substr(key, start, end);
            }
        });
    }

    /**
     * 同时将多个 field-value (字段-值)对设置到哈希表中
     * @param key
     * @param hash
     * @return
     */
    public String hmset(final String key, final Map<String, String> hash) {
        return this.execute(new Function<ShardedJedis, String>() {
            @Override
            public String execute(ShardedJedis shardedJedis) {
                return shardedJedis.hmset(key, hash);
            }
        });
    }

    /**
     * 获取key对应的所有field
     * @param key
     * @return
     */
    public Set<String> hkeys(final String key) {
        return this.execute(new Function<ShardedJedis, Set<String>>() {
            @Override
            public Set<String> execute(ShardedJedis shardedJedis) {
                return shardedJedis.hkeys(key);
            }
        });
    }

    /**
     * 获取key对应的所有val值
     * @param key
     * @return
     */
    public List<String> hvals(final String key) {
        return this.execute(new Function<ShardedJedis, List<String>>() {
            @Override
            public List<String> execute(ShardedJedis shardedJedis) {
                return shardedJedis.hvals(key);
            }
        });
    }

    /**
     * 获取key对应的所有key-value键值对
     * @param key
     * @return
     */
    public Map<String, String> hgetAll(final String key) {
        return this.execute(new Function<ShardedJedis, Map<String, String>>() {
            @Override
            public Map<String, String> execute(ShardedJedis shardedJedis) {
                return shardedJedis.hgetAll(key);
            }
        });
    }

    /**
     * 将当前数据库的 key 移动到给定的数据库 db 当中
     * @param key
     * @param dbIndex
     * @return
     */
    public Long move(final String key, final int dbIndex) {
        return this.execute(new Function<ShardedJedis, Long>() {
            @Override
            public Long execute(ShardedJedis shardedJedis) {
                return shardedJedis.move(key, dbIndex);
            }
        });
    }
}
